package rlog

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/debug"
	"strconv"
	"strings"
	"sync/atomic"

	"gitee.com/terender/sfw/utils"
)

var closed int32
var moduleName = `unkown`

var inited = false

// MasterLogName 主日志的名称
const MasterLogName = `master`

// Init 日志功能初始化
// name 是当前运行的模块的名字，比如 gameserver
// toStd 表示是否将日志输出到stdout
func Init(name string, toStd bool) {
	moduleName = name
	inited = true
	Logger(MasterLogName).OutputToSTD(toStd)
	Rawf("\n")
	Rawf("\n")
	Rawf("\n")
	Rawf(`==========================================================================`)
	Rawf(fmt.Sprintf(`           %v start pid:%v`, name, os.Getpid()))
	Rawf(`==========================================================================`)
	Infof(`[%v] rlog started logging to %s/logs/%s/`, name, utils.ProjectPath(), name)
}

// Quit 日志模块退出
func Quit() {
	atomic.StoreInt32(&closed, 1)
	quitChan := make(chan bool)
	Infof(`[%v] rlog stopped`, moduleName)
	// 对每个RotateLogger 调用Close 传入quitChan
	logManager.Lock()
	len := len(logManager.loggers)
	for _, logger := range logManager.loggers {
		logger.Close(quitChan)
	}
	logManager.Unlock()

	for range quitChan {
		len--
		if len <= 0 {
			close(quitChan)
			break
		}
	}
}

func _goid() int {
	defer func() {
		if err := recover(); err != nil {
			Errorf(fmt.Sprintf("panic recover:panic info:%v", err))
			Rawf(string(debug.Stack()))
		}
	}()

	var buf [64]byte
	n := runtime.Stack(buf[:], false)
	idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
	id, err := strconv.Atoi(idField)
	if err != nil {
		Errorf(fmt.Sprintf("cannot get goroutine id: %v", err))
	}
	return id
}

// Logger 获取指定名称的日志对象
func Logger(name string) *RotateLogger {
	defer func() {
		if err := recover(); err != nil {
			Errorf(fmt.Sprintf("panic recover:panic info:%v", err))
			debug.Stack()
		}
	}()
	if !inited {
		log.Print(`[wanning]日志系统未被正确初始化，请在启动时调用 rlog.Init()`)
		Init(fmt.Sprintf(`unkown_%v`, os.Getpid()), false)
	}
	logManager.Lock()
	defer logManager.Unlock()
	info, ok := logManager.loggers[name]
	if ok {
		return info
	}

	rl := &RotateLogger{
		name:    name,
		message: make(chan []interface{}, 100),
	}
	logManager.loggers[name] = rl
	go rl.printProc()
	return rl
}

func logToMaster(level string, v ...interface{}) {
	v = append([]interface{}{generatePrifex(level)}, v...)
	Logger(MasterLogName).LogRaw(v...)
}

// Rawf 打印原始通知日志
func Rawf(v ...interface{}) { Logger(MasterLogName).LogRaw(v...) }

// Infof 打印通知日志
func Infof(t string, v ...interface{}) { logToMaster(`info`, fmt.Sprintf(t, v...)) }

// Debug 打印调试日志
//func Debug(v ...interface{}) { logToMaster(`debug`, v...) }

// Debugf 打印调试日志
func Debugf(t string, v ...interface{}) { logToMaster(`debug`, fmt.Sprintf(t, v...)) }

// Error 打印错误日志
//func Error(v ...interface{}) { logToMaster(`error`, v...) }

// Errorf 打印错误日志
func Errorf(t string, v ...interface{}) { logToMaster(`error`, fmt.Sprintf(t, v...)) }

// Warn 打印警告日志
//func Warn(v ...interface{}) { logToMaster(`warning`, v...) }

// Warnf 打印警告日志
func Warnf(t string, v ...interface{}) { logToMaster(`warning`, fmt.Sprintf(t, v...)) }
